#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "RPFITS.h"

#define BUFSIZE 1000

/* RPFITS commands numerical definitions to make the code more readable */
#define JSTAT_OPENFILE -3
#define JSTAT_OPENFILE_READHEADER -2
#define JSTAT_READNEXTHEADER -1
#define JSTAT_READDATA 0
#define JSTAT_CLOSEFILE 1
#define JSTAT_SKIPTOEND 2

/* RPFITS return codes definitions to make the code more readable */
#define JSTAT_UNSUCCESSFUL -1
#define JSTAT_SUCCESSFUL 0
#define JSTAT_HEADERNOTDATA 1
#define JSTAT_ENDOFSCAN 2
#define JSTAT_ENDOFFILE 3
#define JSTAT_FGTABLE 4
#define JSTAT_ILLEGALDATA 5

void base_to_ants(int baseline,int *ant1,int *ant2){
  /* the baseline number is just 256*a1 + a2, where
     a1 is antenna 1, and a2 is antenna 2, and a1<=a2 */
  int i,j;
  for (i=1;i<=6;i++){
    for (j=i;j<=6;j++){
      if (baseline==(256*i+j)){
	*ant1=i;
	*ant2=j;
      }
    }
  }
}

int main(int argc,char *argv[]){
  int i,j,k,nfiles=0,this_jstat,baseline,flag,bin,if_no,sourceno,that_jstat;
  int keep_reading,header_number,rpfits_result,ut_h,ut_m,ut_s,read_data;
  int n_ints[6],n_bad[6],ant1,ant2,curr_sourceno;
  char **filenames=NULL,source_name[BUFSIZE],datobs[BUFSIZE],obstype[BUFSIZE];
  char cal[BUFSIZE],onsource[BUFSIZE],slewing[BUFSIZE];
  float *vis=NULL,*wgt=NULL,ut,u,v,w,ra_hrs,dec_deg,last_ut[6],old_ut;

  /* get the list of files */
  for (i=1;i<argc;i++){
    nfiles++;
    filenames=realloc(filenames,nfiles*sizeof(char*));
    if (filenames!=NULL){
      filenames[nfiles-1]=malloc(BUFSIZE*sizeof(char));
    }
    strcpy(filenames[nfiles-1],argv[i]);
  }

  /* go through them one by one and output what they have in them */
  for (i=0;i<nfiles;i++){
    strcpy(names_.file,filenames[i]);
    this_jstat=JSTAT_OPENFILE;
    rpfits_result=rpfitsin_(&this_jstat,vis,wgt,&baseline,&ut,&u,&v,
			    &w,&flag,&bin,&if_no,&sourceno);
    if (this_jstat==JSTAT_UNSUCCESSFUL){
      fprintf(stderr,"Cannot open RPFITS file %s\n",names_.file);
      continue;
    }

    printf(">>> %s:\n",names_.file);
    keep_reading=1;
    header_number=1;
    while (keep_reading){
      this_jstat=JSTAT_READNEXTHEADER;
      rpfits_result=rpfitsin_(&this_jstat,vis,wgt,&baseline,&ut,&u,&v,&w,&flag,&bin,&if_no,&sourceno);
      if (this_jstat==JSTAT_SUCCESSFUL){
	strncpy(datobs,names_.datobs,12);
	datobs[10]='\0';
	vis=realloc(vis,(if_.if_nstok[0]*if_.if_nfreq[0])*sizeof(float));
	that_jstat=JSTAT_READDATA;
	rpfits_result=rpfitsin_(&that_jstat,vis,wgt,&baseline,&ut,&u,&v,&w,&flag,&bin,&if_no,&sourceno);
	ut/=3600.0;
	ut_h=(int)(floorf(ut));
	ut-=(float)ut_h;
	ut*=60.0;
	ut_m=(int)(floorf(ut));
	ut-=(float)ut_m;
	ut*=60.0;
	ut_s=(int)(floorf(ut));
	strncpy(obstype,names_.obstype,16);
 	printf("%12s %02d:%02d:%02d %16s",datobs,ut_h,ut_m,ut_s,obstype);
/* 	for (j=0;j<su_.n_su;j++){ */
/* 	  strncpy(source_name,names_.su_name+j*16,16); */
	strncpy(source_name,names_.su_name+(sourceno-1)*16,16);
	source_name[15]='\0';
/* 	ra_hrs=(doubles_.su_ra[j]*180.0/3.141592654)/15.0; /\* in hours *\/ */
/* 	dec_deg=doubles_.su_dec[j]*180.0/3.141592654; /\* in degrees *\/ */
	ra_hrs=(doubles_.su_ra[sourceno-1]*180.0/3.141592654)/15.0; /* in hours */
	dec_deg=doubles_.su_dec[sourceno-1]*180.0/3.141592654; /* in degrees */
	curr_sourceno=sourceno;
/* 	  if (j==0){ */
	strncpy(cal,names_.su_cal+(sourceno-1)*4,4);
	printf(" %16s %4s %8.5f %9.5f",source_name,cal,ra_hrs,dec_deg);
	for (k=0;k<if_.n_if;k++){
	  printf(" %6.0f (%4.0f %4dc)",doubles_.if_freq[k]/1E6,doubles_.if_bw[k]/1E6,
		 if_.if_nfreq[k]);
	}
	printf(" %3d",param_.intime);
/*       } else { */
/* 	    printf("\n%12s %8s %16s %8.5f %9.5f"," "," ",source_name,ra_hrs,dec_deg); */
/* 	  } */
/*       } */
	read_data=1;
	if ((if_.if_nstok[0]*if_.if_nfreq[0])>0){
	  vis=realloc(vis,2*((if_.if_nstok[0]+1)*(if_.if_nfreq[0]+1))*sizeof(float));
	  wgt=realloc(wgt,2*((if_.if_nstok[0]+1)*(if_.if_nfreq[0]+1))*sizeof(float));
	} else {
	  free(vis); vis=NULL;
	  free(wgt); wgt=NULL;
	}
	for (j=0;j<6;j++){
	  last_ut[j]=-1;
	  n_ints[j]=0;
	  n_bad[j]=0;
	}
	while(read_data){
	  that_jstat=JSTAT_READDATA;
	  rpfits_result=rpfitsin_(&that_jstat,vis,wgt,&baseline,&ut,&u,&v,&w,&flag,&bin,&if_no,&sourceno);
	  if (that_jstat!=JSTAT_SUCCESSFUL){
	    if (that_jstat==JSTAT_ILLEGALDATA){
/* 	      printf("found illegal data, continuing!"); */
	      continue;
	    }
	    if (that_jstat!=JSTAT_FGTABLE){
/* 	      printf("\nbreaking due to result %d",that_jstat); */
	      read_data=0;
	      break;
	    } else {
/* 	      printf("\nfound flag table!"); */
	      that_jstat=JSTAT_READNEXTHEADER;
	      rpfits_result=rpfitsin_(&that_jstat,vis,wgt,&baseline,&ut,&u,&v,&w,&flag,&bin,&if_no,&sourceno);

	      that_jstat=JSTAT_READDATA;
	      rpfits_result=rpfitsin_(&that_jstat,vis,wgt,&baseline,&ut,&u,&v,&w,&flag,&bin,&if_no,&sourceno);
	    }	      
	  }
	  if ((if_no==1)&&(ut>0)&&(bin==1)&&(baseline!=-1)){
/*  	    printf("\n[if = %d ut = %f flag = %d bin = %d sourceno = %d baseline = %d]", */
/*  		   if_no,ut,flag,bin,sourceno,baseline); */
	    if (sourceno!=curr_sourceno){
	      snprintf(onsource,BUFSIZE,"[%d %d %d %d %d %d]",
		       n_ints[0],n_ints[1],n_ints[2],n_ints[3],n_ints[4],n_ints[5]);
	      snprintf(slewing,BUFSIZE,"<%d %d %d %d %d %d>",
		       n_bad[0],n_bad[1],n_bad[2],n_bad[3],n_bad[4],n_bad[5]);
/* 	      printf(" [%d %d %d %d %d %d] <%d %d %d %d %d %d>", */
/* 		     n_ints[0],n_ints[1],n_ints[2],n_ints[3],n_ints[4],n_ints[5], */
/* 		     n_bad[0],n_bad[1],n_bad[2],n_bad[3],n_bad[4],n_bad[5]); */
	      printf(" %-25s %-25s",onsource,slewing);
	      printf("\n");
	      fflush(NULL);
	      for (j=0;j<6;j++){
		last_ut[j]=-1;
		n_ints[j]=0;
		n_bad[j]=0;
	      }
	      old_ut=ut;
	      ut/=3600.0;
	      ut_h=(int)(floorf(ut));
	      ut-=(float)ut_h;
	      ut*=60.0;
	      ut_m=(int)(floorf(ut));
	      ut-=(float)ut_m;
	      ut*=60.0;
	      ut_s=(int)(floorf(ut));
	      ut=old_ut;
	      strncpy(datobs,names_.datobs,12);
	      datobs[10]='\0';
	      printf("%12s %02d:%02d:%02d %16s",datobs,ut_h,ut_m,ut_s,obstype);
	      strncpy(source_name,names_.su_name+(sourceno-1)*16,16);
	      source_name[15]='\0';
	      ra_hrs=(doubles_.su_ra[sourceno-1]*180.0/3.141592654)/15.0; /* in hours */
	      dec_deg=doubles_.su_dec[sourceno-1]*180.0/3.141592654; /* in degrees */
	      curr_sourceno=sourceno;
	      strncpy(cal,names_.su_cal+(sourceno-1)*4,4);
	      printf(" %16s %4s %8.5f %9.5f",source_name,cal,ra_hrs,dec_deg);
	      for (k=0;k<if_.n_if;k++){
		printf(" %6.0f (%4.0f %4dc)",doubles_.if_freq[k]/1E6,doubles_.if_bw[k]/1E6,
		       if_.if_nfreq[k]);
	      }
	      printf(" %3d",param_.intime);
	    }
	    /* only count IF 1, it should always be there */
	    base_to_ants(baseline,&ant1,&ant2);
	    if (flag==0){
	      /* good data */
	      if (last_ut[ant1-1]!=ut){
		n_ints[ant1-1]++;
		last_ut[ant1-1]=ut;
	      }
	    } else {
	      /* probably slewing */
	      if (last_ut[ant1-1]!=ut){
		n_bad[ant1-1]++;
		last_ut[ant1-1]=ut;
	      }
	    }
	  }
	}
	snprintf(onsource,BUFSIZE,"[%d %d %d %d %d %d]",
		 n_ints[0],n_ints[1],n_ints[2],n_ints[3],n_ints[4],n_ints[5]);
	snprintf(slewing,BUFSIZE,"<%d %d %d %d %d %d>",
		 n_bad[0],n_bad[1],n_bad[2],n_bad[3],n_bad[4],n_bad[5]);
/* 	printf(" [%d %d %d %d %d %d] <%d %d %d %d %d %d>", */
/* 	       n_ints[0],n_ints[1],n_ints[2],n_ints[3],n_ints[4],n_ints[5], */
/* 	       n_bad[0],n_bad[1],n_bad[2],n_bad[3],n_bad[4],n_bad[5]); */
	printf(" %-25s %-25s",onsource,slewing);
	printf("\n");
	fflush(NULL);
      } else if (this_jstat==JSTAT_ENDOFFILE){
	keep_reading=0;
      }
      header_number++;
    }
    this_jstat=JSTAT_CLOSEFILE;
    rpfits_result=rpfitsin_(&this_jstat,vis,wgt,&baseline,&ut,&u,&v,&w,&flag,&bin,&if_no,&sourceno);
  }

  exit(0);
}
